/******************************************************************
 * TCP Server主要实现
 * 1. 套接字的初始化
 * 2. 创建epoll模型
 * 3. 添加关心的事件
 * 4. 对已经就绪的事件做处理
 *******************************************************************/
#pragma once
#include <iostream>
#include <string>
#include <memory>
#include <map>

#include <cerrno>
#include <cstring>

#include "Socket.hpp"
#include "epoller.hpp"
#include "Connection.hpp"
#include "Common.h"

using namespace MySocket;
using namespace MyEpoller;
using namespace MyConnection;

namespace MyTCP_Server
{
    const static int maxevents = 20;

    // 设置对服务器的运行状态

    class TCPServer
    {
    public:
        TCPServer(uint16_t port)
            : _socket(new TCP_Server_Socket(port))
            , _epoller(new Epoller())
            , _fd_connection(new std::map<int, Connection *>)
            , _status(Stopping), _maxevents(maxevents)
            , _events(new epoll_event[_maxevents])
        {
        }
        ~TCPServer()
        {
        }
        void Init()
        {
            // 对套接字的初始化
            _socket->ServerInit();
            // 获取监听fd
            int fd = _socket->GetListenfd();
            // 添加监听事件
            _epoller->AddEvent(fd);
            _status = Running;
        }
        void Loop()
        {
            while (_status)
            {
                int ret = _epoller->Wait(_events, _maxevents);
                // 在timeout的事件内有就绪事件
                if (ret > 0)
                {
                    // 处理事件
                    Hander(ret);
                }
                // 在timeout的时间内，没有就绪事件
                else if (ret == 0)
                {
                    std::cout << "没有就绪事件" << std::endl;
                }
                // wait失败
                else
                {
                    _log.LogMessage(ClassFile, Error, "epoll_wait error, 错误原因: %s\n", strerror(errno));
                    exit(Epoll_Wait_Error);
                }
            }
        }

    private:
        // 处理事件
        void Hander(int ready_event_size)
        {
            for (int i = 0; i < ready_event_size; ++i)
            {
                int listenfd = _socket->GetListenfd();
                int cur_fd = _events[i].data.fd;
                // 读取事件就绪 / accept条件就绪
                if (_events[i].events & EPOLLIN)
                {
                    // accept条件就绪
                    if (cur_fd == listenfd)
                    {
                        // 获取连接
                        _socket->Accept();
                        // 添加关心的事件的fd
                        _epoller->AddEvent(_socket->Getfd());
                    }
                    // recv条件就绪
                    else
                    {
                        // recv读这里我们希望每个fd都有自己的recv/send缓冲区
                        (*_fd_connection)[cur_fd] = new Connection(cur_fd);
                        auto one_connect = (*_fd_connection)[cur_fd];
                        one_connect->Recv();
                    }
                }
            }
        }

    private:
        std::unique_ptr<Socket> _socket;                             // 用于套接字处理
        std::unique_ptr<Epoller> _epoller;                           // 用于对fd事件进行等待
        std::unique_ptr<std::map<int, Connection *>> _fd_connection; // 用于建立每个fd与buffer的连接
        int _status;                                                 // 表示当前服务器是否运行
        int _maxevents;                                              // 最大接收event的个数
        epoll_event *_events;                                        // 接收当前所有有就绪事件的fd
    };
}